#pragma once

#include "parameter.h"
#include "solver.h"

// 适应度是越大越好还是越小越好
#define MINIMIZE_FITNESS
// #define MAXIMIZE_FITNESS


struct PSOPara
{
	int dim_{};							// 参数维度（position和velocity的维度）
	int particle_num_{};				// 粒子个数
	int max_iter_num_{};				// 最大迭代次数
	int *dt_ = nullptr;					// 时间步长
	double *wstart_ = nullptr;		    // 初始权重
	double *wend_ = nullptr;			// 终止权重
	double *C1_ = nullptr;				// 加速度因子
	double *C2_ = nullptr;			    // 加速度因子
	int *upper_bound_ = nullptr;		// position搜索范围上限
	int *lower_bound_ = nullptr;		// position搜索范围下限
	int *range_interval_ = nullptr;		// position搜索区间长度
	int results_dim_ = 0;				// results的维度

	PSOPara()= default;

	PSOPara(int dim, bool hasBound = true)
	{
		dim_ = dim;
		dt_ = new int[dim_];
		wstart_ = new double[dim_];
		wend_ = new double[dim_];
		C1_ = new double[dim_];
		C2_ = new double[dim_];
		if (hasBound)
		{
			upper_bound_ = new int[dim_];
			lower_bound_ = new int[dim_];
			range_interval_ = new int[dim_];
		}
	}

	~PSOPara()
	{
		delete[]upper_bound_;
		delete[]lower_bound_;
		delete[]range_interval_;
		delete[]dt_;
		delete[]wstart_;
		delete[]wend_;
		delete[]C1_;
		delete[]C2_;
	}
};

struct Particle
{
	int dim_{};							// 参数维度（position和velocity的维度）
    long long fitness_{};
	int *position_ = nullptr;
	int *velocity_ = nullptr;
	int *best_position_ = nullptr;
    long long best_fitness_{};
	int *results_ = nullptr;			// 一些需要保存出的结果
	int results_dim_ = 0;				// results_的维度

	Particle()= default;

    Particle(int dim, int *position, int *velocity, int *best_position, long long best_fitness);

	~Particle()
	{
		delete[]position_;
		delete[]velocity_;
		delete[]best_position_;
		delete[]results_;
	}
};

typedef long long(*ComputeFitness)(Particle& particle);

class PSOOptimizer
{
public:
	int particle_num_{};				// 粒子个数
	int max_iter_num_{};				// 最大迭代次数
	int curr_iter_{};					// 当前迭代次数
	int dim_{};							// 参数维度（position和velocity的维度）

	Particle *particles_ = nullptr;		// 所有粒子
	
	int *upper_bound_ = nullptr;		// position搜索范围上限
	int *lower_bound_ = nullptr;		// position搜索范围下限
	int *range_interval_ = nullptr;		// position搜索区间长度

	int *dt_ = nullptr;					// 时间步长
	double *wstart_ = nullptr;			// 初始权重
	double *wend_ = nullptr;			// 终止权重
	double *w_ = nullptr;				// 当前迭代权重
	double *C1_ = nullptr;				// 加速度因子
	double *C2_ = nullptr;				// 加速度因子

    long long all_best_fitness_{};		// 全局最优粒子的适应度值
	int *all_best_position_ = nullptr;	// 全局最优粒子的poistion
	int *results_ = nullptr;			// 一些需要保存出的结果
	int results_dim_ = 0;				// results的维度
    int rand_max = 0;                   // 随机数最大值

	ComputeFitness fitness_fun_ = nullptr;	// 适应度函数

public:
	PSOOptimizer() = default;

	PSOOptimizer(PSOPara* pso_para, ComputeFitness fitness_fun);

	~PSOOptimizer();

	// 初始化所有粒子参数
	void InitialAllParticles(const vector<int>& init_position);

	// 初始化第i个粒子参数
	void InitialParticle(int i, vector<int> init_position);

    // 获取int随机数
    int GetIntRand(int N = 550000);

	// 获取双精度随机数（默认精度为0.0001）
	double GetDoubleRand(int N = 550000);

	// 计算该粒子的适应度值
    long long GetFitness(Particle& particle);

	// 更新所有粒子参数
	void UpdateAllParticles();

	// 更新第i个粒子
	void UpdateParticle(int i);

	// 获取当前迭代的权重
	void GetInertialWeight();
};

long long FitnessFunction(Particle& particle);
